package base;

import java.io.ByteArrayOutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

import org.jdom.Document;
import org.jdom.Element;

import xml.document.DocumentHelper;

public class ReflectionUtils {
	
	public static void analyzeObject(Object o) throws Exception{
		Class<? extends Object> objectClass = o.getClass();
		
		Element root = new Element("class"); 
		root.setAttribute("name", objectClass.getName());
		
		appendAnnotations(root, objectClass.getAnnotations());
		appendFields(root, objectClass.getDeclaredFields(), o);
		
		Document doc = new Document(root);
		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
		DocumentHelper.write(doc, buffer);
		
		System.out.print( new String(buffer.toByteArray()) );
	}

	private static void appendFields(Element root, Field[] fields, Object o) throws Exception{
		if (fields == null || fields.length == 0){
			return;
		}
		
		Element fieldsEl = new Element("fields");
		
		for (Field field : fields) {
			field.setAccessible(true);
			
			appendField(fieldsEl, field, o);
		}
		
		root.addContent(fieldsEl);
	}

	private static void appendField(Element root, Field field, Object o) throws Exception{
		Element newField = new Element("field");
		
		newField.setAttribute("Type", field.getType().getName());
		newField.setAttribute("Name", field.getName() );
		
		
		Element valueEl = new Element("value");
		Object object = field.get(o);
		if (null == object){
			valueEl.setAttribute("Value", "null");
		} else {
			valueEl.setAttribute("type", object.getClass().getName());
			valueEl.setAttribute("value", object.toString());

		}
		newField.addContent(valueEl);
		
		root.addContent(newField);
	}

	private static void appendAnnotations(Element root, Annotation[] annotations) {
		if (annotations == null || annotations.length == 0){
			return;
		}
		
		Element annotationsEl = new Element("annotations");

		for (Annotation annotation : annotations) {
			appendAnnotation(annotationsEl, annotation);
		}
		
		root.addContent(annotationsEl);
	}

	private static void appendAnnotation(Element root, Annotation annotation) {
		Element newAnnotation = new Element("annotation");
		newAnnotation.setAttribute("name", annotation.annotationType().getName());
		root.addContent(newAnnotation);
	}
	
}
